package com.github.aloxc.plugin;

import com.github.aloxc.plugin.restplus.i18n.I18Bundle;
import com.github.aloxc.plugin.restplus.common.Consts;
import com.github.aloxc.plugin.restplus.component.VTree;
import com.google.gson.*;
import com.intellij.openapi.editor.colors.FontPreferences;

import javax.swing.*;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.tree.*;
import java.awt.*;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class TreeTest extends JFrame {
    private VTree responseTree;
    TreeTest(){
        setTitle("树操作");
        setBounds(400, 400, 400, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        DefaultMutableTreeNode root = new DefaultMutableTreeNode("根节点");//创建根节点
        DefaultMutableTreeNode nodeFirst = new DefaultMutableTreeNode("一级子节点A");//创建一级节点
        root.add(nodeFirst);// 将一级节点添加到根节点
        DefaultMutableTreeNode nodeSecond = new DefaultMutableTreeNode("二级子节点", false);//创建不允许有子节点的二级节点

        nodeFirst.add(nodeSecond);//将二级节点添加到一级节点
        root.add(new DefaultMutableTreeNode("一级子节点B"));//创建一级节点

        responseTree = new VTree(Color.GRAY);// 利用根节点直接创建树
        responseTree.setShowLineNumber(true);
        responseTree.setRowHeight(22);
        SimpleAttributeSet  keyAttr = new SimpleAttributeSet();
        StyleConstants.setFontSize(keyAttr, 14);
        Font font = new Font(FontPreferences.DEFAULT_FONT_NAME, Font.PLAIN, 14);
        responseTree.setFont(font);
        responseTree.setPreferredSize(new Dimension(400,400));
        String content = "\n" +
                "{\"message\":\"success感谢又拍云(upyun.com)提供CDN赞助\",\"status\":200,\"date\":\"20200528\",\"time\":\"2020-05-28 15:10:11\",\"cityInfo\":{\"city\":\"天津市\",\"citykey\":\"101030100\",\"parent\":\"天津\",\"updateTime\":\"14:31\"},\"data\":{\"shidu\":\"20%\",\"pm25\":18.0,\"pm10\":31.0,\"quality\":\"良\",\"wendu\":\"31\",\"ganmao\":\"极少数敏感人群应减少户外活动\",\"forecast\":[{\"date\":\"28\",\"high\":\"高温 33℃\",\"low\":\"低温 20℃\",\"ymd\":\"2020-05-28\",\"week\":\"星期四\",\"sunrise\":\"04:50\",\"sunset\":\"19:28\",\"aqi\":24,\"fx\":\"南风\",\"fl\":\"<3级\",\"type\":\"晴\",\"notice\":\"愿你拥有比阳光明媚的心情\"},{\"date\":\"29\",\"high\":\"高温 32℃\",\"low\":\"低温 18℃\",\"ymd\":\"2020-05-29\",\"week\":\"星期五\",\"sunrise\":\"04:49\",\"sunset\":\"19:28\",\"aqi\":26,\"fx\":\"东南风\",\"fl\":\"<3级\",\"type\":\"晴\",\"notice\":\"愿你拥有比阳光明媚的心情\"},{\"date\":\"30\",\"high\":\"高温 34℃\",\"low\":\"低温 20℃\",\"ymd\":\"2020-05-30\",\"week\":\"星期六\",\"sunrise\":\"04:49\",\"sunset\":\"19:29\",\"aqi\":46,\"fx\":\"东南风\",\"fl\":\"3-4级\",\"type\":\"晴\",\"notice\":\"愿你拥有比阳光明媚的心情\"},{\"date\":\"31\",\"high\":\"高温 33℃\",\"low\":\"低温 18℃\",\"ymd\":\"2020-05-31\",\"week\":\"星期日\",\"sunrise\":\"04:48\",\"sunset\":\"19:30\",\"aqi\":43,\"fx\":\"东风\",\"fl\":\"4-5级\",\"type\":\"多云\",\"notice\":\"阴晴之间，谨防紫外线侵扰\"},{\"date\":\"01\",\"high\":\"高温 33℃\",\"low\":\"低温 18℃\",\"ymd\":\"2020-06-01\",\"week\":\"星期一\",\"sunrise\":\"04:48\",\"sunset\":\"19:31\",\"aqi\":76,\"fx\":\"西北风\",\"fl\":\"3-4级\",\"type\":\"阴\",\"notice\":\"不要被阴云遮挡住好心情\"},{\"date\":\"02\",\"high\":\"高温 30℃\",\"low\":\"低温 19℃\",\"ymd\":\"2020-06-02\",\"week\":\"星期二\",\"sunrise\":\"04:46\",\"sunset\":\"19:31\",\"aqi\":26,\"fx\":\"东风\",\"fl\":\"3级\",\"type\":\"多云\",\"notice\":\"阴晴之间，谨防紫外线侵扰\"},{\"date\":\"03\",\"high\":\"高温 34℃\",\"low\":\"低温 18℃\",\"ymd\":\"2020-06-03\",\"week\":\"星期三\",\"sunrise\":\"04:46\",\"sunset\":\"19:32\",\"aqi\":29,\"fx\":\"西南风\",\"fl\":\"2级\",\"type\":\"晴\",\"notice\":\"愿你拥有比阳光明媚的心情\"},{\"date\":\"04\",\"high\":\"高温 35℃\",\"low\":\"低温 18℃\",\"ymd\":\"2020-06-04\",\"week\":\"星期四\",\"sunrise\":\"04:45\",\"sunset\":\"19:33\",\"aqi\":89,\"fx\":\"西北风\",\"fl\":\"3级\",\"type\":\"多云\",\"notice\":\"阴晴之间，谨防紫外线侵扰\"},{\"date\":\"05\",\"high\":\"高温 37℃\",\"low\":\"低温 25℃\",\"ymd\":\"2020-06-05\",\"week\":\"星期五\",\"sunrise\":\"04:45\",\"sunset\":\"19:33\",\"aqi\":79,\"fx\":\"西北风\",\"fl\":\"3级\",\"type\":\"晴\",\"notice\":\"愿你拥有比阳光明媚的心情\"},{\"date\":\"06\",\"high\":\"高温 22℃\",\"low\":\"低温 16℃\",\"ymd\":\"2020-06-06\",\"week\":\"星期六\",\"sunrise\":\"04:51\",\"sunset\":\"19:24\",\"aqi\":44,\"fx\":\"北风\",\"fl\":\"3级\",\"type\":\"小雨\",\"notice\":\"雨虽小，注意保暖别感冒\"},{\"date\":\"07\",\"high\":\"高温 33℃\",\"low\":\"低温 18℃\",\"ymd\":\"2020-06-07\",\"week\":\"星期日\",\"sunrise\":\"04:45\",\"sunset\":\"19:34\",\"aqi\":10,\"fx\":\"东南风\",\"fl\":\"3级\",\"type\":\"小雨\",\"notice\":\"雨虽小，注意保暖别感冒\"},{\"date\":\"08\",\"high\":\"高温 37℃\",\"low\":\"低温 25℃\",\"ymd\":\"2020-06-08\",\"week\":\"星期一\",\"sunrise\":\"04:45\",\"sunset\":\"19:35\",\"aqi\":14,\"fx\":\"西南风\",\"fl\":\"2级\",\"type\":\"多云\",\"notice\":\"阴晴之间，谨防紫外线侵扰\"},{\"date\":\"09\",\"high\":\"高温 33℃\",\"low\":\"低温 21℃\",\"ymd\":\"2020-06-09\",\"week\":\"星期二\",\"sunrise\":\"04:44\",\"sunset\":\"19:36\",\"aqi\":38,\"fx\":\"东南风\",\"fl\":\"3级\",\"type\":\"小雨\",\"notice\":\"雨虽小，注意保暖别感冒\"},{\"date\":\"10\",\"high\":\"高温 34℃\",\"low\":\"低温 24℃\",\"ymd\":\"2020-06-10\",\"week\":\"星期三\",\"sunrise\":\"04:44\",\"sunset\":\"19:36\",\"aqi\":52,\"fx\":\"东南风\",\"fl\":\"3级\",\"type\":\"晴\",\"notice\":\"愿你拥有比阳光明媚的心情\"},{\"date\":\"11\",\"high\":\"高温 34℃\",\"low\":\"低温 24℃\",\"ymd\":\"2020-06-11\",\"week\":\"星期四\",\"sunrise\":\"04:44\",\"sunset\":\"19:37\",\"aqi\":23,\"fx\":\"西风\",\"fl\":\"2级\",\"type\":\"阴\",\"notice\":\"不要被阴云遮挡住好心情\"}],\"yesterday\":{\"date\":\"27\",\"high\":\"高温 33℃\",\"low\":\"低温 18℃\",\"ymd\":\"2020-05-27\",\"week\":\"星期三\",\"sunrise\":\"04:50\",\"sunset\":\"19:27\",\"aqi\":60,\"fx\":\"东南风\",\"fl\":\"<3级\",\"type\":\"阴\",\"notice\":\"不要被阴云遮挡住好心情\"}}}";
        showInTree(content);
        add(responseTree, BorderLayout.WEST);


        setVisible(true);

    }
    private Map jsonEleTreeMap = new HashMap();


    public void showInTree(String text) {
        //创建树节点
        JsonParser parser = new JsonParser();
        JsonElement jsonEle = parser.parse(text);
        Gson gson = new GsonBuilder().setPrettyPrinting().create();

        jsonEleTreeMap = new HashMap();
        jsonEleTreeMap.put(responseTree.hashCode(), jsonEle);
        DefaultMutableTreeNode root = objNode("JSON");
        DefaultTreeModel model = (DefaultTreeModel) responseTree.getModel();
        try {
            createJsonTree(jsonEle, root);
            model.setRoot(root);
            setNodeIcon(responseTree);
            expandTree(responseTree, new TreePath(root));
        } catch (Exception ex) {
            root.removeAllChildren();
            model.setRoot(root);
            showMessageDialog(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.response.tree.jsontree.exception.text"), ex.getMessage());
        }
    }

    private void expandTree(JTree tree, TreePath parent) {
        TreeNode node = (TreeNode) parent.getLastPathComponent();
        if (node.getChildCount() >= 0) {
            for (Enumeration<?> e = node.children(); e.hasMoreElements(); ) {
                TreeNode n = (TreeNode) e.nextElement();
                TreePath path = parent.pathByAddingChild(n);
                expandTree(tree, path);
            }
        }
        tree.expandPath(parent);
    }

    public final static String SPLIT = " : ";

    public final static String SIGN = "-";

    public final static String C_NULL = "k";
    public final static String C_NUM = "n";
    public final static String C_OBJ = "o";
    public final static String C_ARR = "a";
    public final static String C_STR = "v";
    public final static String C_BOOL = "b";

    public final static String S_NULL = C_NULL + SIGN;
    public final static String S_NUM = C_NUM + SIGN;
    public final static String S_OBJ = C_OBJ + SIGN;
    public final static String S_ARR = C_ARR + SIGN;
    public final static String S_STR = C_STR + SIGN;
    public final static String S_BOOL = C_BOOL + SIGN;


    public static DefaultMutableTreeNode nullNode(String key) {
        return treeNode(S_NULL + key + SPLIT + "<null>");
    }

    public static DefaultMutableTreeNode nullNode(int index) {
        return nullNode(fkey(index));
    }


    /**
     * 构造json树结构.
     *
     * @param obj   JsonElement
     * @param pNode DefaultMutableTreeNode
     */
    private void createJsonTree(JsonElement obj, DefaultMutableTreeNode pNode) {
        if (obj.isJsonNull()) {
            pNode.add(nullNode("NULL"));
        } else if (obj.isJsonArray()) {
            createJsonArray(obj.getAsJsonArray(), pNode, "[0]");
        } else if (obj.isJsonObject()) {
            JsonObject child = obj.getAsJsonObject();
            // DefaultMutableTreeNode node = objNode(key);
            createJsonObject(child, pNode);
            // pNode.add(node);
        } else if (obj.isJsonPrimitive()) {
            JsonPrimitive pri = obj.getAsJsonPrimitive();
            formatJsonPrimitive("PRI", pri, pNode);
        }
    }


    /**
     * 处理json数组.
     *
     * @param arr
     * @param pNode
     * @param key
     */
    private void createJsonArray(JsonArray arr, DefaultMutableTreeNode pNode, String key) {
        int index = 0;
        DefaultMutableTreeNode child = arrNode(key);
        for (Iterator it = arr.iterator(); it.hasNext(); ) {
            JsonElement el = (JsonElement) it.next();
            if (el.isJsonObject()) {
                JsonObject obj = el.getAsJsonObject();
                DefaultMutableTreeNode node = objNode(index);
                createJsonObject(obj, node);
                child.add(node);
            } else if (el.isJsonArray()) {
                JsonArray lst = el.getAsJsonArray();
                createJsonArray(lst, child, fkey(index));
            } else if (el.isJsonNull()) {
                child.add(nullNode(index));
            } else if (el.isJsonPrimitive()) {
                formatJsonPrimitive(fkey(index), el.getAsJsonPrimitive(), child);
            }
            ++index;
        }
        pNode.add(child);
    }

    /**
     * 处理jsoon对象.
     *
     * @param obj
     * @param pNode
     */
    private void createJsonObject(JsonObject obj, DefaultMutableTreeNode pNode) {
        for (Map.Entry<String, JsonElement> el : obj.entrySet()) {
            String key = el.getKey();
            JsonElement val = el.getValue();
            if (val.isJsonNull()) {
                pNode.add(nullNode(key));
            } else if (val.isJsonArray()) {
                createJsonArray(val.getAsJsonArray(), pNode, key);
            } else if (val.isJsonObject()) {
                JsonObject child = val.getAsJsonObject();
                DefaultMutableTreeNode node = objNode(key);
                createJsonObject(child, node);
                pNode.add(node);
            } else if (val.isJsonPrimitive()) {
                JsonPrimitive pri = val.getAsJsonPrimitive();
                formatJsonPrimitive(key, pri, pNode);
            }
        }

    }

    private void formatJsonPrimitive(String key, JsonPrimitive pri, DefaultMutableTreeNode pNode) {
        if (pri.isJsonNull()) {
            pNode.add(nullNode(key));
        } else if (pri.isNumber()) {
            pNode.add(numNode(key, pri.getAsString()));
        } else if (pri.isBoolean()) {
            pNode.add(boolNode(key, pri.getAsBoolean()));
        } else if (pri.isString()) {
            pNode.add(strNode(key, pri.getAsString()));
        } else if (pri.isJsonArray()) {
            createJsonArray(pri.getAsJsonArray(), pNode, key);
        } else if (pri.isJsonObject()) {
            JsonObject child = pri.getAsJsonObject();
            DefaultMutableTreeNode node = objNode(key);
            createJsonObject(child, node);
            pNode.add(node);
        } else if (pri.isJsonPrimitive()) {
            formatJsonPrimitive(key, pri.getAsJsonPrimitive(), pNode);
        }
    }

    private void setNodeIcon(JTree tree) {
        tree.setCellRenderer(new DefaultTreeCellRenderer() {
            @Override
            public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
                super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
                String tmp = node.toString();
                SimpleAttributeSet  keyAttr = new SimpleAttributeSet();
                StyleConstants.setFontSize(keyAttr, 16);
                Font font = new Font(FontPreferences.DEFAULT_FONT_NAME, Font.PLAIN, 16);
                this.setFont(font);
                if (tmp.startsWith(S_ARR)) {
                    this.setIcon(Consts.Icons.A);
                    this.setText(tmp.substring(2));

                } else if (tmp.startsWith(S_STR)) {
                    this.setIcon(Consts.Icons.V);
                    this.setText(tmp.substring(2));
                } else if (tmp.startsWith(S_OBJ)) {
                    this.setIcon(Consts.Icons.O);
                    this.setText(tmp.substring(2));
                } else if (tmp.startsWith(S_NUM)) {
                    this.setIcon(Consts.Icons.N);
                    this.setText(tmp.substring(2));
                } else if (tmp.startsWith(S_NULL)) {
                    this.setIcon(Consts.Icons.K);
                    this.setText(tmp.substring(2));
                } else if (tmp.startsWith(S_BOOL)) {
                    this.setIcon(Consts.Icons.V);
                    this.setText(tmp.substring(2));
                } else {
                    this.setIcon(Consts.Icons.V);
                    this.setText(tmp.substring(2));
                }
                return this;
            }
        });
    }

    public static DefaultMutableTreeNode numNode(String key, String val) {
        return treeNode(S_NUM + key + SPLIT + val);
    }


    public static DefaultMutableTreeNode boolNode(String key, Boolean val) {
        String sVal = "false";
        if (val) {
            sVal = "true";
        }
        return treeNode(S_BOOL + key + SPLIT + sVal);
    }


    public static DefaultMutableTreeNode strNode(String key, String val) {
        return treeNode(S_STR + key + SPLIT + "\"" + val + "\"");
    }


    public static DefaultMutableTreeNode objNode(String key) {
        return treeNode(S_OBJ + key);
    }

    public static DefaultMutableTreeNode objNode(int index) {
        return objNode(fkey(index));
    }

    public static DefaultMutableTreeNode arrNode(String key) {
        return treeNode(S_ARR + key);
    }



    public static DefaultMutableTreeNode treeNode(String str) {
        return new DefaultMutableTreeNode(str);
    }

    public static String fkey(int index) {
        return "[" + index + "]";
    }



    private void showMessageDialog(String title, String msg) {

    }







    public static void main(String[] args) {
        new TreeTest();
    }
}
